using System.Text;
using System.Threading.Tasks;
using SqlSugar;
using System.Linq;
using HBKY.Shop.Model;
using System;
using System.Linq.Expressions;
using HBKY.Shop.Common.Extension;
using MongoDB.Driver.Linq;

namespace HBKY.Shop.Service
{
    public static class QueryableExtension
    {
        /// <summary>
        /// 分页拓展方法
        /// where T : BaseEntity
        /// </summary>
        /// <param name="queryable"></param>
        /// <param name="query"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static async Task<PageList<T>> ToPageList<T>(this ISugarQueryable<T> queryable, PageQuery query)
        {
            PageList<T> result = new PageList<T>();
            if (queryable == default) return result;
            RefAsync<int> total = 0;
            if (query.PageIndex > 0 && query.PageSize > 0)
            {
                //总页数计算
                result.PageSize = query.PageSize;
                result.Data = await queryable.ToPageListAsync(query.PageIndex, query.PageSize, total);
                result.PageCount = (total + query.PageSize - 1) / query.PageSize;
            }
            result.TotalCount = total;
            return result;
        }

        /// <summary>
        /// 请求排序（客户端传参）
        /// </summary>
        /// <param name="queryable"></param>
        /// <param name="query"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static ISugarQueryable<T> ApplySort<T>(this ISugarQueryable<T> queryable, PageQuery query)
        {
            if (queryable == default) return queryable;
            return queryable.OrderByIF(!string.IsNullOrEmpty(query.Sort),
                GenerateOrderByField(query.Sort, query.Order));
        }

        /// <summary>
        /// 添加排序字段
        /// </summary>
        /// <returns></returns>
        public static ISugarQueryable<T> ApplyOrder<T>(this ISugarQueryable<T> queryable, Expression<Func<T, object>> expression, OrderByType type = OrderByType.Asc)
        {
            if (queryable == default) return queryable;
            return queryable.OrderBy(expression, type);
        }

        /// <summary>
        /// 组织排序条件
        /// </summary>
        /// <param name="sort">排序列</param>
        /// <param name="order">排序方式 0降序  1升序</param>
        /// <returns></returns>
        private static string GenerateOrderByField(string sort, string order)
        {
            StringBuilder sb = new StringBuilder();
            if (!string.IsNullOrEmpty(sort))
            {
                sb.Append(sort);
                sb.Append(" ");
                sb.Append((string.IsNullOrWhiteSpace(order) || order == OrderByType.Asc.StrValue()) ? OrderByType.Asc.ToString() : OrderByType.Desc.ToString());
            }
            return sb.ToString();
        }


        #region mogondb

        /// <summary>
        /// 分页列表
        /// </summary>
        public static async Task<PageList<T>> ToPageList<T>(this IMongoQueryable<T> queryable, PageQuery query)
        {
            PageList<T> result = new PageList<T>();
            if (queryable == default) return result;
            RefAsync<int> total = 0;
            if (query.PageIndex > 0 && query.PageSize > 0)
            {
                //总页数计算
                result.PageSize = query.PageSize;
                if (query.Order == OrderByType.Asc.StrValue())
                {
                    queryable.OrderBy(ConvertToPropertyExpression<T>(query.Sort));
                }
                else
                {
                    queryable.OrderByDescending(ConvertToPropertyExpression<T>(query.Sort));
                }
                total = await queryable.CountAsync();
                result.Data = queryable.Skip((query.PageIndex - 1) * query.PageSize).Take(query.PageSize).AsEnumerable();
                result.PageCount = (total + query.PageSize - 1) / query.PageSize;
            }
            result.TotalCount = total;
            return result;
        }

        /// <summary>
        /// 排序字段转化lambda 表达式
        /// </summary>
        public static Expression<Func<TEntity, double>> ConvertToPropertyExpression<TEntity>(string propertyName)
        {
            var lambdaParam = Expression.Parameter(typeof(TEntity));
            var lambdaBody = Expression.Property(lambdaParam, propertyName);
            return Expression.Lambda<Func<TEntity, double>>(lambdaBody, lambdaParam);
        }
        #endregion
    }
}